﻿#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.BaseData;
using TodoApi.Controllers.DTO;
using TodoApi.Enum;
using TodoApi.Models;
using TodoApi.Parameter;
using TodoApi.Services;

namespace TodoApi.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize(Roles = "超级管理员")]
    public class StudentController : ControllerBase
    {
        private readonly StudentContext _context;
        private readonly IMapper _mapper;
        private readonly IStudentServices _studentservices;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public StudentController(StudentContext context, IMapper mapper, IStudentServices studentServices, IHttpContextAccessor httpContextAccessor)
        {
            _context = context;
            _mapper = mapper;
            _studentservices = studentServices;
            _httpContextAccessor = httpContextAccessor;
        }


        [HttpGet]
        
        public async Task<IActionResult> Get()
        {
            var result = await _studentservices.Get();
            if(result.Count()==0||result == null)
            {
                return NotFound("没有数据");
            }
            return  Ok(result) ;
        }
        [HttpPost]
        public async Task<ResultData> Update(StudentDTO stu)
        {
            return await _studentservices.Update(stu);
        }
        [HttpGet]
        public string GetUserName()
        {
            //var Claim =   _httpContextAccessor.HttpContext.User.Claims.ToList();
            //var userName = Claim.Where(x => x.Type == "昵称").First().Value;
            return _httpContextAccessor.HttpContext.User.FindFirstValue("昵称");
        }


        //[Authorize(Roles = "管理员")]
        // GET: api/Student
        [HttpPost]
        public async Task<IActionResult> GetStudent([FromQuery] SelectParameter select)
        {
            //先获取一下数据
            List<StudentDTO> students = await _context.Student.Include(x => x.Classes).Select(x => _mapper.Map<StudentDTO>(x)).ToListAsync();
            var resudata = await _context.Student.Include(x => x.Classes).ToListAsync();
            //简单的写一下
            //如果有搜索的话那就搜一下
            if (!string.IsNullOrEmpty(select.Search))
            {
                students = students.Where(x => x.Name.Contains(select.Search)).ToList();
            }
            //简单的排下序,就按名字吧,可以继续添加参数来
            if (select.Sort)
            {
                students = students.OrderBy(x => x.Name).ToList();
            }
            if (select.MaxAge != null)
            {
                students = students.Where(x => x.Age >= select.MinAge && x.Age <= select.MaxAge).ToList();
            }
            //如果设置了长度的话那就这样咯
            if (select.Length > 0)
            {
                students = students.Skip(select.Start).Take(select.Length).ToList();
            }

            if (students.Count == 0)
                return Ok("没有这个用户");
            return Ok(students);
        }

        // GET: api/Student/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Student>> GetStudent(Guid id)
        {
            var Student = await _context.Student.FindAsync(id);

            if (Student == null)
            {
                return NotFound();
            }

            return Student;
        }

        // PUT: api/Student/5
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPut("{id}")]
        public async Task<IActionResult> PutStudent(Guid id, Student Student)
        {
            if (id != Student.Id)
            {
                return BadRequest();
            }

            _context.Entry(Student).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!StudentExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Student
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPost]
        //public async Task<ActionResult<Student>> PostStudent(Student Student)
        //{
        //    //当传入的对象没有id时就是一串长长的0了，就自己创建了一个，实现添加的操作了
        //    if (Student.Id == Guid.Parse("00000000-0000-0000-0000-000000000000"))
        //    {
        //        //创建一个ID
        //        Student.Id = Guid.NewGuid();
        //        //把要添加的实体数据放入Add中，这仅仅跟踪这条数据而没有对数据库进行操作
        //        _context.Student.Add(Student);
        //    }
        //    else
        //    {
        //        //如果输入了Id的话判断下是不是指定输入id的
        //        Student todo = await _context.Student.FindAsync(Student.Id);
        //        //没找到这个Id的话那就是添加咯
        //        if(todo==null)
        //        {
        //            _context.Student.Add(Student);

        //        }
        //        else
        //        {
        //            //有这个ID那就是更新了
        //            _context.Update(Student);
        //        }
        //    }
        //    //这个方法就是把上下文中的所有更改保存到数据库中了
        //    await _context.SaveChangesAsync();
        //    //给GetStudent这个方法传个Id来查找然后返回
        //    return CreatedAtAction("GetStudent", new { id = Student.Id }, Student);
        //}



        public async Task<IActionResult> PostStudent(StudentDTO studentDTO)
        {
            var student = _mapper.Map<Student>(studentDTO);
            //查询这个classes的数据放进去
            student.Classes = await _context.Set<Classes>().Where(x => x.Id == Guid.Parse(studentDTO.ClassId)).FirstOrDefaultAsync();
            //当传入的对象没有id时就是一串长长的0了，就自己创建了一个，实现添加的操作了
            if (student.Id == Guid.Parse("00000000-0000-0000-0000-000000000000"))
            {
                student.AdmissionTime = DateTime.Now;
                student.Id = Guid.NewGuid();
                
                //把要添加的实体数据放入Add中，这仅仅跟踪这条数据而没有对数据库进行操作
                _context.Student.Add(student);

            }
            else
            {
                //否则的话就对这条数据进行更新了咯
                student.AdmissionTime = _context.Set<Student>().Where(x => x.Id == student.Id).Select(x => x.AdmissionTime).FirstOrDefault();
                _context.Update(student);
            }
            //这个方法就是把上下文中的所有更改保存到数据库中了
            await _context.SaveChangesAsync();
            //给GetStudent这个方法传个Id来查找然后返回
            Response.StatusCode = 200;
            //return CreatedAtAction(nameof(GetStudent), new { id = student.Id }, student);
            //return _mapper.Map<StudentDTO>(await _context.Student.Where(x => x.Id == student.Id).FirstOrDefaultAsync());
            return Ok(_mapper.Map<StudentDTO>(student));
        }
        [HttpPut("{id}")]
        public async void Put(Guid id,[FromBody]StudentDTO studentDTO)
        {
            //var student = _mapper.Map<Student>(studentDTO);
            //_context.Entry(student).State = EntityState.Modified;
            //_context.SaveChanges();

            var student = _context.Student.Find(id);
            if(student != null)
            {
                student = _mapper.Map<Student>(studentDTO);
                student.Classes = _context.Classes.Find(Guid.Parse(studentDTO.ClassId));
                await _context.SaveChangesAsync();
            }
            
        }
        [HttpPut("{id}")]
        public async Task<IActionResult> PutAutoMapper(Guid id, [FromBody] StudentDTO studentDTO)
        {
            if(studentDTO.Id != id)
            {
                return BadRequest();
            }
            var student = await _context.Student.FindAsync(id);
            studentDTO.AdmissionTime = student.AdmissionTime;
            if (student != null)
            {
                _mapper.Map(studentDTO,student);
                student.Classes = _context.Classes.Find(Guid.Parse(studentDTO.ClassId));
                 _context.SaveChanges();
            }
            else
            {
                return NotFound();
            }

            return NoContent();


        }

        [HttpDelete("{id}")]
        public async Task<IActionResult> Delete(Guid id)
        {
            var student = await (from a in _context.Student
                           where a.Id == id
                           select a).SingleOrDefaultAsync();
            if(student != null)
            {
                _context.Student.Remove(student);
                await _context.SaveChangesAsync();
                return NoContent();
            }
            else
            {
                return NotFound("没有删除的数据");
            }
        }

        [HttpDelete("list/{ids}")]
        public async Task<IActionResult> DeleteRange(string ids)
        {
            List<Guid> deleteList = JsonSerializer.Deserialize<List<Guid>>(ids);
            var student = await(from a in _context.Student
                                where deleteList.Contains(a.Id)
                                select a).ToListAsync();
            if(student != null)
            {
                 _context.Student.RemoveRange(student);
                return NoContent();
            }
            return NotFound("没有删除的数据");
        }


        [HttpPost("test")]
        public async Task<ActionResult<Student>> test(Student Student)
        {
            _context.Student.Add(Student);
            await _context.SaveChangesAsync();

            //return CreatedAtAction("GetStudent", new { id = Student.Id }, Student);
            return CreatedAtAction(nameof(GetStudent), new { id = Student.Id }, Student);
        }

        // DELETE: api/Student/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteStudent(Guid id)
        {
            //查找这个id的实体
            var Student = await _context.Student.FindAsync(id);
            //避免出错就判断一下
            if (Student == null)
            {
                return NotFound();
            }
            //这里需要放入实体数据进去跟踪所以上面就查找了咯
            //_context.Student.Remove(Student);
            //常规的保存哈
            await _context.SaveChangesAsync();

            return NoContent();
        }

        private bool StudentExists(Guid id)
        {
            return _context.Student.Any(e => e.Id == id);
        }
    }
}
